package com.http;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.easysoft.commons.utils.StringUtils;

public class HttpClient {

	private static Logger logger = LoggerFactory.getLogger(HttpClient.class);

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static String doGet(final String url) throws IOException {
		return doGet(url, null, 0, null, 50000);
	}

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static String doGet(final String url, final int timeout) throws IOException {
		return doGet(url, null, 0, null, timeout);
	}

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static String doGet(final String url, final String hostname, final int port, final String scheme) throws IOException {
		return doGet(url, hostname, port, scheme, 50000);
	}

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static String doGet(final String url, final String hostname, final int port, final String scheme, final int timeout)
			throws IOException {

		logger.info("调用URI={}", url);

		CloseableHttpClient client = HttpClients.createDefault();
		HttpHost proxy = null;

		try {
			if (StringUtils.isNotNullAndBlank(hostname) && StringUtils.isNotNullAndBlank(scheme)) {
				proxy = new HttpHost(hostname, port, scheme);
			}

			RequestConfig config = RequestConfig.custom().setProxy(proxy).setSocketTimeout(timeout).setConnectTimeout(timeout)
					.setConnectionRequestTimeout(timeout).setCircularRedirectsAllowed(true).build();

			HttpGet httpGet = new HttpGet(url);
			httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0");
			httpGet.setConfig(config);

			ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

				public String handleResponse(final HttpResponse response) throws IOException {
					int status = response.getStatusLine().getStatusCode();
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						return entity != null ? EntityUtils.toString(entity, Consts.UTF_8) : null;
					}
					else {
						logger.error("Unexpected response status: " + status);
						return null;
					}
				}
			};

			return client.execute(httpGet, responseHandler);

		}
		finally {
			client.close();
		}
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @param parameters
	 *            请求参数
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPost(final String url, final Map<String, String> parameters) throws Exception {
		return doPost(url, parameters, null, 0, null, 50000);
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址
	 * @param parameters
	 *            请求参数
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPost(final String url, final Map<String, String> parameters, final int timeout) throws Exception {
		return doPost(url, parameters, null, 0, null, timeout);
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @param parameters
	 *            请求参数
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPost(final String url, final Map<String, String> parameters, final String hostname, final int port,
								final String scheme) throws Exception {
		return doPost(url, parameters, hostname, port, scheme, 50000);
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址
	 * @param parameters
	 *            请求参数
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPost(final String url, final Map<String, String> parameters, final String hostname, final int port,
								final String scheme, final int timeout) throws Exception {

		logger.info("调用URI={}", url);

		CloseableHttpClient httpclient = HttpClients.createDefault();

		try {
			HttpHost proxy = null;
			if (StringUtils.isNotNullAndBlank(hostname) && StringUtils.isNotNullAndBlank(scheme)) {
				proxy = new HttpHost(hostname, port, scheme);
			}

			RequestConfig config = RequestConfig.custom().setProxy(proxy).setSocketTimeout(timeout).setConnectTimeout(timeout)
					.setConnectionRequestTimeout(timeout).setCircularRedirectsAllowed(true).build();

			HttpPost httpPost = new HttpPost(url);
			httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0");
			httpPost.setConfig(config);
			if (parameters != null) {
				List<NameValuePair> params = new ArrayList<NameValuePair>();
				for (Entry<String, String> parameter : parameters.entrySet()) {
					params.add(new BasicNameValuePair(parameter.getKey(), parameter.getValue()));
				}
				httpPost.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
			}

			ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

				public String handleResponse(final HttpResponse response) throws IOException {
					int status = response.getStatusLine().getStatusCode();
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						return entity != null ? EntityUtils.toString(entity, Consts.UTF_8) : null;
					}
					else {
						logger.error("Unexpected response status: " + status);
						return "";
					}
				}
			};

			return httpclient.execute(httpPost, responseHandler);

		}
		finally {
			httpclient.close();
		}
	}

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static byte[] doGetByte(final String url) throws IOException {
		return doGetByte(url, null, 0, null, 50000);
	}

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static byte[] doGetByte(final String url, final int timeout) throws IOException {
		return doGetByte(url, null, 0, null, timeout);
	}

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static byte[] doGetByte(final String url, final String hostname, final int port, final String scheme) throws IOException {
		return doGetByte(url, hostname, port, scheme, 50000);
	}

	/**
	 * 执行GET请求
	 *
	 * @param url
	 *            请求地址
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws IOException
	 */
	public static byte[] doGetByte(final String url, final String hostname, final int port, final String scheme, final int timeout)
			throws IOException {

		logger.info("调用URI={}", url);

		CloseableHttpClient client = HttpClients.createDefault();
		HttpHost proxy = null;

		try {
			if (StringUtils.isNotNullAndBlank(hostname) && StringUtils.isNotNullAndBlank(scheme)) {
				proxy = new HttpHost(hostname, port, scheme);
			}

			RequestConfig config = RequestConfig.custom().setProxy(proxy).setSocketTimeout(timeout).setConnectTimeout(timeout)
					.setConnectionRequestTimeout(timeout).setCircularRedirectsAllowed(true).build();

			HttpGet httpGet = new HttpGet(url);
			httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0");
			httpGet.setConfig(config);

			ResponseHandler<byte[]> responseHandler = new ResponseHandler<byte[]>() {

				public byte[] handleResponse(final HttpResponse response) throws IOException {
					int status = response.getStatusLine().getStatusCode();
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						return entity != null ? EntityUtils.toByteArray(entity) : null;
					}
					else {
						logger.error("Unexpected response status: " + status);
						return null;
					}
				}
			};

			return client.execute(httpGet, responseHandler);

		}
		finally {
			client.close();
		}
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @param xmlData
	 *            XML格式的请求内容
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPostXML(final String url, final String xmlData) throws Exception {
		return doPostXML(url, xmlData, null, 0, null, 50000);
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址
	 * @param xmlData
	 *            XML格式的请求内容
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPostXML(final String url, final String xmlData, final int timeout) throws Exception {
		return doPostXML(url, xmlData, null, 0, null, timeout);
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址，默认5秒钟超时
	 * @param xmlData
	 *            XML格式的请求内容
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPostXML(final String url, final String xmlData, final String hostname, final int port, final String scheme)
			throws Exception {
		return doPostXML(url, xmlData, hostname, port, scheme, 50000);
	}

	/**
	 * 执行POST请求
	 *
	 * @param url
	 *            请求地址
	 * @param xmlData
	 *            XML格式的请求内容
	 * @param hostname
	 *            网络代理服务器IP
	 * @param port
	 *            网络代理服务器端口
	 * @param scheme
	 *            网络代理类型：http
	 * @param timeout
	 *            网络请求超时时间
	 * @return 请求返回结果
	 * @throws Exception
	 */
	public static String doPostXML(final String url, final String xmlData, final String hostname, final int port, final String scheme,
								   final int timeout) throws Exception {

		logger.info("调用URI={}", url);

		CloseableHttpClient httpclient = HttpClients.createDefault();

		try {
			HttpHost proxy = null;
			if (StringUtils.isNotNullAndBlank(hostname) && StringUtils.isNotNullAndBlank(scheme)) {
				proxy = new HttpHost(hostname, port, scheme);
			}

			StringEntity  entity = new StringEntity(xmlData);
			entity.setContentType("application/x-www-form-urlencoded");

			RequestConfig config = RequestConfig.custom().setProxy(proxy).setSocketTimeout(timeout).setConnectTimeout(timeout)
					.setConnectionRequestTimeout(timeout).setCircularRedirectsAllowed(true).build();

			HttpPost httpPost = new HttpPost(url);
			httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0");
			httpPost.addHeader("Content-Type", "text/xml");
			httpPost.addHeader("charset", "utf-8");
			httpPost.setEntity(entity);
			httpPost.setConfig(config);

			ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

				public String handleResponse(final HttpResponse response) throws IOException {
					int status = response.getStatusLine().getStatusCode();
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						return entity != null ? EntityUtils.toString(entity, Consts.UTF_8) : null;
					}
					else {
						logger.error("Unexpected response status: " + status);
						return "";
					}
				}
			};

			return httpclient.execute(httpPost, responseHandler);

		}
		finally {
			httpclient.close();
		}
	}

}
